#pragma once
#include "../common/message.hpp"
#include "../common/net.hpp"
#include <future>

namespace myrpc{
    namespace client{
        // 客户端请求消息管理类
        class Requestor {
        public:
            using ptr = std::shared_ptr<Requestor>;
            using ReqCallBack = std::function<void(const BaseMessage::ptr &)>;
            using AsyncFuture = std::future<BaseMessage::ptr>;
            // 请求描述结构体
            class ReqDescirbe {
            public:
                using ptr = std::shared_ptr<ReqDescirbe>;
                BaseMessage::ptr _req_msg;                 // 请求消息基类指针
                RType _rtype;                              // 响应消息的处理类型
                std::promise<BaseMessage::ptr> _rsp_msg;   // 响应消息基类指针 对响应消息进行封装
                ReqCallBack _req_cb;                       // 请求对应的回调处理
            };

            // 收到响应消息后的回调处理
            void onResponse(const BaseConnection::ptr &conn, BaseMessage::ptr &rsp_msg){
                std::string id = rsp_msg->getMsgId();
                client_logger->DEBUG("收到响应 -> ID: %s", id.c_str());
                auto rdp = getReqDescribe(id);
                if (rdp.get() == nullptr){
                    client_logger->ERROR("未找到对应的请求描述!");
                    return;
                }
                if (rdp->_rtype == RType::REQ_ASYNC){
                    client_logger->DEBUG("响应 ID: %s, 匹配到异步请求, 设置 Promise...", id.c_str());
                    rdp->_rsp_msg.set_value(rsp_msg);
                } 
                else if (rdp->_rtype == RType::REQ_CALLBACK){
                    client_logger->DEBUG("响应 ID: %s, 匹配到回调请求, 执行回调...", id.c_str());
                    if (rdp->_req_cb){
                        rdp->_req_cb(rsp_msg);
                    }
                }
                else{
                    client_logger->ERROR("响应 ID: %s, 回调请求类型未知!");
                }
                delReqDescribe(id);
            }

            // 发送请求 异步处理响应消息对象
            bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req_msg, BaseMessage::ptr &rsp_msg){
                AsyncFuture async_future;                
                bool ret = send(conn, req_msg, async_future);
                if (ret == false){
                    return false;
                }
                rsp_msg = async_future.get();             // 从future对象中获取响应结果
                return true;
            }
            bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req_msg, AsyncFuture &async_future){
                auto rdp = newReqDescribe(req_msg, RType::REQ_ASYNC);
                if (rdp.get() == nullptr){
                    client_logger->ERROR("构造请求描述对象失败!");
                    return false;
                }
                conn->send(req_msg);
                async_future = rdp->_rsp_msg.get_future(); // 获取关联的future对象
                return true;
            }
            // 发送请求 回调处理响应消息对象
            bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req_msg, const ReqCallBack &cb){
                auto rdp = newReqDescribe(req_msg, RType::REQ_CALLBACK, cb);
                if (rdp.get() == nullptr){
                    client_logger->ERROR("构造请求描述对象失败!");
                    return false;
                }
                conn->send(req_msg);
                return true;
            }

        private:
            // 在集合中增加新的请求描述
            ReqDescirbe::ptr newReqDescribe(const BaseMessage::ptr &req_msg, RType rtype, const ReqCallBack &cb=ReqCallBack()){
                std::unique_lock<std::mutex> lock(_mutex);
                auto rdp=std::make_shared<ReqDescirbe>();
                rdp->_req_msg = req_msg;
                rdp->_rtype = rtype;
                rdp->_req_cb = cb;
                _reqs_desc.insert(std::make_pair(req_msg->getMsgId(), rdp));
                return rdp;
            }
            // 从集合中获取目标请求描述
            ReqDescirbe::ptr getReqDescribe(const std::string &id){
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _reqs_desc.find(id);
                if (it == _reqs_desc.end()){
                    return ReqDescirbe::ptr();
                }
                return it->second;
            }
            // 从集合中删除目标请求描述
            void delReqDescribe(const std::string &id){
                std::unique_lock<std::mutex> lock(_mutex);
                _reqs_desc.erase(id);
            }

        private:
            std::mutex _mutex;
            // 建立请求ID和请求描述之间的映射关系 用哈希表存储
            std::unordered_map<std::string, ReqDescirbe::ptr> _reqs_desc;
        };
    }
}